package com.appkubes.fintech.restful.application.sms.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.appkubes.fintech.common.exption.BusinessException;
import com.appkubes.fintech.restful.application.sms.entity.eo.SmsCodeEO;
import com.appkubes.fintech.restful.application.sms.entity.dto.SmsCodeDTO;
import com.appkubes.fintech.restful.application.sms.profile.AliSMSConfigModel;
import com.appkubes.fintech.restful.application.sms.profile.TemplateParam;
import com.appkubes.fintech.restful.application.sms.service.SmsService;
import com.appkubes.fintech.restful.util.MapBeanUtil;
import com.appkubes.fintech.restful.util.MyOkHttpUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Author: wuzhijian
 * @Date: 2019/12/26
 * @Description:
 */
@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

    private final static int DEFAULT_CODE_LENGTH = 6;

    private static final String REDIS_PREFIX_KYLIN_PLUGIN_FINTECH_MESSAGE_CODE = "kylin_plugin_fintech:message_code:";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AliSMSConfigModel aliSMMallSystemConfigModel;

    @Override
    public String send(String phone) throws ClientException {
        String key = REDIS_PREFIX_KYLIN_PLUGIN_FINTECH_MESSAGE_CODE + phone;
        String redisCode = stringRedisTemplate.opsForValue().get(key);
        if (redisCode != null) {
            log.info("手机号为[" + phone + "]，从缓存中获取验证码为：" + redisCode);
            return redisCode;
        }
        // 初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile(aliSMMallSystemConfigModel.getDefaultProfile(),
                aliSMMallSystemConfigModel.getAccessKeyId(), aliSMMallSystemConfigModel.getAccessKeySecret());

        DefaultProfile.addEndpoint(aliSMMallSystemConfigModel.getRegion(),
                aliSMMallSystemConfigModel.getProduct(),
                aliSMMallSystemConfigModel.getDomain());

        IAcsClient acsClient = new DefaultAcsClient(profile);
        SendSmsRequest smsRequest = new SendSmsRequest();
        String code = "";
        Random random = new Random();
        for (int i = 0; i < 4; i++) {
            code += random.nextInt(10);
        }
        TemplateParam param = new TemplateParam();
        param.setCode(code);
        param.setProduct(aliSMMallSystemConfigModel.getTemplateParamProduct());

        //必填，设置短信接收号码
        smsRequest.setPhoneNumbers(phone);
        //必填，设置签名名称，应严格按"签名名称"填写，请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/sign
        smsRequest.setSignName(aliSMMallSystemConfigModel.getSignName());
        //必填，设置模板CODE，应严格按"模板CODE"填写, 请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/template
        smsRequest.setTemplateCode(aliSMMallSystemConfigModel.getTemplateCode());
        //可选，设置模板参数, 假如模板中存在变量需要替换则为必填项
        smsRequest.setTemplateParam(JSONObject.toJSONString(param, false));

        //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
        //smsRequest.setSmsUpExtendCode("90998");

        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
        //smsRequest.setOutId("myoutid");
        SendSmsResponse smsResponse = acsClient.getAcsResponse(smsRequest);
        stringRedisTemplate.opsForValue().set(key, code, 120, TimeUnit.SECONDS);
        return code;
    }

    @Override
    public boolean valid(String phone, String code) {
        String key = REDIS_PREFIX_KYLIN_PLUGIN_FINTECH_MESSAGE_CODE + phone;
        String redisCode = stringRedisTemplate.opsForValue().get(key);
        if (redisCode != null && redisCode.equalsIgnoreCase(code)) {
            stringRedisTemplate.delete(key);
            return true;
        }
        return false;
    }

    private static String randomCode() {
        StringBuilder code = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < DEFAULT_CODE_LENGTH; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }
}
